home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Utilities / PalmLink / src / PL_Serial.c < prev    next >
C/C++ Source or Header  |  2000-05-06  |  13KB  |  439 lines

  1. /**
  2.  * PalmLink -- Connect 3Com Palm with Amiga
  3.  *
  4.  * Serial interface
  5.  *
  6.  * (C) 1998-2000 Richard Körber <rkoerber@gmx.de>
  7.  *
  8.  *------------------------------------------------------------------
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  *
  24.  * You must not use this source code to gain profit of any kind!
  25.  */
  26.  
  27. #include "palmlink_glob.h"
  28.  
  29. #include <devices/serial.h>
  30. #include <devices/timer.h>
  31.  
  32.  
  33.  
  34. /*------------------------------------------------------**
  35. ** Name:        OpenPalmSerial                 protected
  36. **
  37. ** Funktion:    Open a serial connection
  38. **
  39. ** Parameter:   socket    Socket
  40. **              device    Devicename
  41. **              unit      Deviceunit
  42. **              baud      Baudrate
  43. ** Ergebnis:    success
  44. //>
  45. ** Bemerkungen:
  46. **
  47. ** Revision:    31. Mai 1998, 13:40:02
  48. */
  49. int OpenPalmSerial
  50. (
  51.   struct PL_Socket *sock,
  52.   STRPTR device,
  53.   ULONG  unit,
  54.   ULONG  baud
  55. )
  56. {
  57.   struct PL_Serial *ser;
  58.   LONG err;
  59.  
  60.   err = PLERR_NOMEM;
  61.   ser = (struct PL_Serial *)AllocVec(sizeof(struct PL_Serial),MEMF_PUBLIC|MEMF_CLEAR);
  62.   if(ser)
  63.   {
  64.     if(ser->timerport = CreateMsgPort())          // Create timer message port
  65.     {
  66.       if(ser->timerio = (struct timerequest *)CreateIORequest(ser->timerport,sizeof(struct timerequest)))
  67.       {
  68.         err = PLERR_NORESOURCE;
  69.         if(!OpenDevice("timer.device",UNIT_VBLANK,(struct IORequest *)ser->timerio,0L))
  70.         {
  71.           ser->timerbase = ser->timerio->tr_node.io_Device;
  72.           err = PLERR_NOMEM;
  73.           if(ser->serport = CreateMsgPort())      // create serial message port
  74.           {
  75.             if(ser->serio = (struct IOExtSer *)CreateIORequest(ser->serport,sizeof(struct IOExtSer)))
  76.             {
  77.               err = PLERR_NORESOURCE;
  78.               ser->serio->io_SerFlags |= SERF_7WIRE;
  79. //              ser->serio->io_SerFlags &= ~SERF_7WIRE;
  80.               if(!OpenDevice(device,unit,(struct IORequest *)ser->serio,0L))
  81.               {
  82.                 ser->serio->IOSer.io_Command = SDCMD_SETPARAMS;
  83.                 ser->serio->io_Baud          = baud;
  84.                 ser->serio->io_StopBits      = 1;
  85.                 ser->serio->io_ReadLen       = 8;
  86.                 ser->serio->io_WriteLen      = 8;
  87.                 ser->serio->io_SerFlags     |= SERF_RAD_BOOGIE|SERF_XDISABLED|SERF_7WIRE;
  88.                 ser->serio->io_ExtFlags      = 0;
  89.                 err = PLERR_SERIAL;
  90.                 if(  (!DoIO((struct IORequest *)ser->serio))
  91.                    ||(ser->serio->IOSer.io_Error == SerErr_NoDSR))
  92.                 {
  93.                   sock->serial = ser;
  94.                   sock->lastError = PLERR_OKAY;
  95.                   ser->currBaud = baud;
  96.                   return(TRUE);
  97.                 }
  98.                 CloseDevice((struct IORequest *)ser->serio);
  99.               }
  100.               DeleteIORequest(ser->serio);
  101.             }
  102.             DeleteMsgPort(ser->serport);
  103.           }
  104.         }
  105.         DeleteIORequest(ser->timerio);
  106.       }
  107.       DeleteMsgPort(ser->timerport);
  108.     }
  109.     FreeVec(ser);
  110.   }
  111.   sock->lastError = err;
  112.   return(FALSE);
  113. }
  114. //<
  115.  
  116. /*------------------------------------------------------**
  117. ** Name:        ClosePalmSerial                protected
  118. **
  119. ** Funktion:    Schließt die serielle Verbindung
  120. **
  121. ** Parameter:   sock      Socket
  122. //>
  123. ** Bemerkungen: Wird nur aufgerufen, wenn OpenPalmSerial()
  124. **              _nicht_ fehlgeschlagen ist.
  125. **
  126. ** Revision:    31. Mai 1998, 14:05:05
  127. */
  128. void ClosePalmSerial
  129. (
  130.   struct PL_Socket *sock
  131. )
  132. {
  133.   struct PL_Serial *ser = sock->serial;
  134.   CloseDevice((struct IORequest *)ser->serio);
  135.   DeleteIORequest(ser->serio);
  136.   DeleteMsgPort(ser->serport);
  137.   DeleteIORequest(ser->timerio);
  138.   DeleteMsgPort(ser->timerport);
  139.   FreeVec(ser);
  140. }
  141. //<
  142.  
  143. /*------------------------------------------------------**
  144. ** Name:        PL_RawSetRate                     public
  145. **
  146. ** Funktion:    Stellt die Baudrate ein
  147. **
  148. ** Parameter:   socket    Socket
  149. **              baud      Baudrate
  150. ** Ergebnis:    success
  151. //>
  152. ** Bemerkungen:
  153. **
  154. ** Revision:     5. Juni 1998, 00:15:11
  155. */
  156. __saveds __asm int PL_RawSetRate
  157. (
  158.   register __a0 APTR socket,
  159.   register __d0 ULONG baud
  160. )
  161. {
  162.   struct PL_Socket *sock = (struct PL_Socket *)socket;
  163.   struct PL_Serial *ser = sock->serial;
  164.   sock->lastError = PLERR_OKAY;
  165.  
  166. #ifdef SERDEBUG
  167.     Printf("SER: Change baud to %ld\n",baud);
  168. #endif
  169.  
  170.   if(ser->currBaud == baud) return(TRUE);         // has already been set
  171.   ser->serio->IOSer.io_Command = SDCMD_SETPARAMS;
  172.   ser->serio->io_Baud          = baud;
  173.   if(  (!DoIO((struct IORequest *)ser->serio))
  174.      ||(ser->serio->IOSer.io_Error == SerErr_NoDSR))
  175.   {
  176.     ser->currBaud = baud;
  177.     Delay(10);                                    // take some time to settle
  178.     return(TRUE);
  179.   }
  180.  
  181. #ifdef SERDEBUG
  182.   Printf("PL_RawSetRate Error %ld\n",ser->serio->IOSer.io_Error);
  183. #endif
  184.   sock->lastError = PLERR_SERIAL;
  185.   return(FALSE);
  186. }
  187. //<
  188.  
  189. /*------------------------------------------------------**
  190. ** Name:        PL_RawRead                        public
  191. **
  192. ** Funktion:    Liest Rohdaten vom Palm, wartet bis
  193. **              genügend Daten vorhanden sind, oder bis
  194. **              Timeout.
  195. **
  196. ** Parameter:   socket    Socket
  197. **              buffer    Datenpuffer
  198. **              length    Länge des Puffers
  199. ** Ergebnis:    Gelesene Länge oder 0: Fehler
  200. //>
  201. ** Bemerkungen:
  202. **
  203. ** Revision:    31. Mai 1998, 16:28:12
  204. */
  205. __saveds __asm LONG PL_RawRead
  206. (
  207.   register __a0 APTR socket,
  208.   register __a1 APTR buffer,
  209.   register __d0 LONG length
  210. )
  211. {
  212.   struct PL_Socket *sock = (struct PL_Socket *)socket;
  213.   struct PL_Serial *ser  = sock->serial;
  214.   ULONG waitmask =   (1L<<ser->serport->mp_SigBit)
  215.                    | (sock->abortmask);
  216.   ULONG signals;
  217.  
  218. #ifdef SERDEBUG
  219.   UWORD i;
  220. #endif
  221.  
  222.   sock->lastError = PLERR_OKAY;
  223.  
  224.   ser->serio->IOSer.io_Command = CMD_READ;
  225.   ser->serio->IOSer.io_Length  = length;
  226.   ser->serio->IOSer.io_Data    = buffer;
  227.  
  228.   ser->timerio->tr_node.io_Command = TR_ADDREQUEST;
  229.   ser->timerio->tr_time.tv_secs    = sock->timeout;
  230.   ser->timerio->tr_time.tv_micro   = 0;
  231.  
  232.   if(sock->timeout)
  233.   {
  234.     SendIO((struct IORequest *)ser->timerio);     // start timer
  235.     waitmask |= (1L<<ser->timerport->mp_SigBit);
  236.   }
  237.   SendIO((struct IORequest *)ser->serio);         // send command
  238.  
  239.   for(;;)
  240.   {
  241.     signals = Wait(waitmask);
  242.     if(signals & sock->abortmask)
  243.     {
  244.       sock->lastError = PLERR_ABORTED;
  245.       AbortIO((struct IORequest *)ser->serio);    // Abort serial command
  246.       WaitIO((struct IORequest *)ser->serio);     // wait until abortion is acknowledged
  247.       if(sock->timeout)
  248.       {
  249.         AbortIO((struct IORequest *)ser->timerio);  // stop timer
  250.         WaitIO((struct IORequest *)ser->timerio);   // wait until timer is stopped
  251.       }
  252.       return 0;
  253.     }
  254.  
  255.     if(CheckIO((struct IORequest *)ser->serio))   // request done?
  256.     {
  257.       WaitIO((struct IORequest *)ser->serio);     // Wait for request to arrive
  258.       if(sock->timeout)
  259.       {
  260.         AbortIO((struct IORequest *)ser->timerio);  // abort timer
  261.         WaitIO((struct IORequest *)ser->timerio);   // wait until timer is aborted
  262.       }
  263. #ifdef SERDEBUG
  264.   for(i=0; i<length; i++)
  265.     Printf("A<-P %02lx\n",((UBYTE *)buffer)[i]);
  266. #endif
  267.       if(ser->serio->IOSer.io_Error)              // Error?
  268.       {
  269.         if(ser->serio->IOSer.io_Error != SerErr_NoDSR)
  270.         {
  271. #ifdef SERDEBUG
  272.   Printf("PL_RawRead Error %ld\n",ser->serio->IOSer.io_Error);
  273. #endif
  274.           sock->lastError = PLERR_SERIAL;
  275.           return 0;                               // Nothing was read
  276.         }
  277.       }
  278.       break;                                      // Leave loop
  279.     }
  280.  
  281.     if(sock->timeout && CheckIO((struct IORequest *)ser->timerio)) // Timeout?
  282.     {
  283.       WaitIO((struct IORequest *)ser->timerio);   // wait until timer returns
  284.       AbortIO((struct IORequest *)ser->serio);    // abort serial request
  285.       WaitIO((struct IORequest *)ser->serio);     // wait until request is aborted
  286.       sock->lastError = PLERR_TIMEOUT;            // Timeout
  287.       return 0;                                   // failure (Timeout)
  288.     }
  289.   }
  290.  
  291.   return length;                                  // everything was read
  292. }
  293. //<
  294.  
  295. /*------------------------------------------------------**
  296. ** Name:        PL_RawWrite                       public
  297. **
  298. ** Funktion:    Sendet Rohdaten zum Palm
  299. **
  300. ** Parameter:   socket    Socket
  301. **              buffer    Datenpuffer
  302. **              length    Länge des Puffers
  303. ** Ergebnis:    Geschriebene Länge oder 0: Fehler
  304. //>
  305. ** Bemerkungen:
  306. **
  307. ** Revision:    31. Mai 1998, 16:35:59
  308. */
  309. __saveds __asm LONG PL_RawWrite
  310. (
  311.   register __a0 APTR socket,
  312.   register __a1 APTR buffer,
  313.   register __d0 LONG length
  314. )
  315. {
  316.   struct PL_Socket *sock = (struct PL_Socket *)socket;
  317.   struct PL_Serial *ser  = sock->serial;
  318.   ULONG waitmask =   (1L<<ser->serport->mp_SigBit)
  319.                    | (sock->abortmask);
  320.   ULONG signals;
  321.  
  322. #ifdef SERDEBUG
  323.   UWORD i;
  324. #endif
  325.  
  326.   sock->lastError = PLERR_OKAY;
  327.  
  328.   ser->serio->IOSer.io_Command = CMD_WRITE;
  329.   ser->serio->IOSer.io_Length  = length;
  330.   ser->serio->IOSer.io_Data    = buffer;
  331.  
  332.   ser->timerio->tr_node.io_Command = TR_ADDREQUEST;
  333.   ser->timerio->tr_time.tv_secs    = sock->timeout;
  334.   ser->timerio->tr_time.tv_micro   = 0;
  335.  
  336.   if(sock->timeout) {
  337.     SendIO((struct IORequest *)ser->timerio);       // Start timer
  338.     waitmask |= (1L<<ser->timerport->mp_SigBit);
  339.   }
  340.   SendIO((struct IORequest *)ser->serio);         // Start request
  341.  
  342.   for(;;)
  343.   {
  344.     signals = Wait(waitmask);
  345.  
  346.     if(signals & sock->abortmask)
  347.     {
  348.       sock->lastError = PLERR_ABORTED;
  349.       AbortIO((struct IORequest *)ser->serio);    // stop serial request
  350.       WaitIO((struct IORequest *)ser->serio);     // wait until stopped
  351.       if(sock->timeout) {
  352.         AbortIO((struct IORequest *)ser->timerio);  // stop timer
  353.         WaitIO((struct IORequest *)ser->timerio);   // wait until timer is stopped
  354.       }
  355.       return 0;
  356.     }
  357.  
  358.     if(CheckIO((struct IORequest *)ser->serio))   // request finished?
  359.     {
  360.       WaitIO((struct IORequest *)ser->serio);     // wait for the request to return
  361.       if(sock->timeout) {
  362.         AbortIO((struct IORequest *)ser->timerio);  // stop timer
  363.         WaitIO((struct IORequest *)ser->timerio);   // wait until timer is stopped
  364.       }
  365. #ifdef SERDEBUG
  366.   for(i=0; i<length; i++)
  367.     Printf("A->P %02lx\n",((UBYTE *)buffer)[i]);
  368. #endif
  369.       if(ser->serio->IOSer.io_Error)              // Error?
  370.       {
  371.         if(ser->serio->IOSer.io_Error != SerErr_NoDSR)
  372.         {
  373. #ifdef SERDEBUG
  374.   Printf("PL_RawWrite Error %ld\n",ser->serio->IOSer.io_Error);
  375. #endif
  376.           sock->lastError = PLERR_SERIAL;
  377.           return 0;                               // Nothing was read
  378.         }
  379.       }
  380.       break;                                      // break loop
  381.     }
  382.  
  383.     if(sock->timeout && CheckIO((struct IORequest *)ser->timerio)) // Timeout?
  384.     {
  385.       WaitIO((struct IORequest *)ser->timerio);   // wait for the timer to return
  386.       AbortIO((struct IORequest *)ser->serio);    // stop serial request
  387.       WaitIO((struct IORequest *)ser->serio);     // wait for request to return
  388.       sock->lastError = PLERR_TIMEOUT;            // timeout
  389.       return 0;                                   // failure (Timeout)
  390.     }
  391.   }
  392.  
  393.   return length;                                  // Everything was read
  394. }
  395. //<
  396.  
  397. /*------------------------------------------------------**
  398. ** Name:        PL_RawFlush                       public
  399. **
  400. ** Funktion:    Leert den Sende- und Empfangspuffer
  401. **
  402. ** Parameter:   socket    Socket
  403. ** Ergebnis:    success
  404. //>
  405. ** Bemerkungen:
  406. **
  407. ** Revision:     9. September 1998, 11:20:26
  408. */
  409. __saveds __asm int PL_RawFlush
  410. (
  411.   register __a0 APTR socket
  412. )
  413. {
  414.   struct PL_Socket *sock = (struct PL_Socket *)socket;
  415.   struct PL_Serial *ser  = sock->serial;
  416.   sock->lastError = PLERR_OKAY;
  417.  
  418.   ser->serio->IOSer.io_Command = CMD_FLUSH;
  419.   DoIO((struct IORequest *)ser->serio);           // Put command
  420.  
  421.   if(ser->serio->IOSer.io_Error)              // Error?
  422.   {
  423.     if(ser->serio->IOSer.io_Error != SerErr_NoDSR)
  424.     {
  425. #ifdef SERDEBUG
  426.   Printf("PL_RawFlush Error %ld\n",ser->serio->IOSer.io_Error);
  427. #endif
  428.       sock->lastError = PLERR_SERIAL;
  429.       return FALSE;
  430.     }
  431.   }
  432.  
  433.   return TRUE;
  434. }
  435. //<
  436.  
  437.  
  438. /********************************************************************/
  439.